package com.puff.web.mvc;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import com.puff.framework.asm.reflect.MethodAccess;
import com.puff.web.view.View;

/**
 * Executor
 */
public final class Executor {

	public final String beanId;
	public final String controllerKey;
	public final String executorKey;
	public final String requestMethod;
	protected final Class<?> returnType;
	protected final Class<?>[] argTypes;
	public final String methodName;
	private final int methodIdx;
	public final String[] interceptors;
	protected final boolean report;
	private final MethodAccess access;
	private int[] paramIdx;
	private int[] compareIdx;
	private String[] compare;
	private final ExcutorErrorHandler errorHandler;

	public Executor(String beanId, String controllerKey, String executorKey, String requestMethod, Method method, int methodIdx, String[] interceptors, boolean report,
			MethodAccess access, ExcutorErrorHandler errorHandler) {
		this.beanId = beanId;
		this.controllerKey = controllerKey;
		this.executorKey = executorKey;
		this.requestMethod = requestMethod;
		this.returnType = method.getReturnType();
		this.argTypes = method.getParameterTypes();
		this.methodName = method.getName();
		this.interceptors = interceptors;
		this.report = report;
		this.methodIdx = methodIdx;
		this.access = access;
		this.errorHandler = errorHandler;
		if (executorKey.contains("$")) {
			String[] arr = executorKey.split("/");
			List<String> compareList = new ArrayList<String>();
			List<Integer> paramIdx = new ArrayList<Integer>();
			List<Integer> compareIdx = new ArrayList<Integer>();
			for (int i = 1; i < arr.length;) {
				String str = arr[i];
				if (str.contains("$")) {
					paramIdx.add(i++);
				} else {
					compareList.add(str);
					compareIdx.add(i++);
				}
			}
			this.compare = new String[compareList.size()];
			for (int i = 0; i < compareList.size(); i++) {
				this.compare[i] = compareList.get(i);
			}
			this.paramIdx = new int[paramIdx.size()];
			for (int i = 0; i < paramIdx.size(); i++) {
				this.paramIdx[i] = paramIdx.get(i);
			}
			this.compareIdx = new int[compareIdx.size()];
			for (int i = 0; i < compareIdx.size(); i++) {
				this.compareIdx[i] = compareIdx.get(i);
			}
		}
	}

	public int[] getParamIdx() {
		return paramIdx;
	}

	public int[] getCompareIdx() {
		return compareIdx;
	}

	public String[] getCompare() {
		return compare;
	}

	protected View execute(Object target, Object[] args) {
		return (View) access.invoke(target, methodIdx, args);
	}

	public View handleExecption(Throwable e) {
		return errorHandler.handleExecption(this, e);
	}

}
